<?php
/**
 * @author Artur Bier <izatop@gmail.com>
 * @package Db.Result
 *
 * @copyright TinyWEB CMS
 * @link http://tinywebcms.ru
 * @link http://cms.vingrad.ru
 * @version SVN: $Id$ 
 */
 
/**
 * DbResultSelect
 */
class DbResultSelect extends DbResult implements IteratorAggregate
{
    
    /**
     * константы для fetchArray()
     */
    const ASSOC = MYSQLI_ASSOC;
    const NUM   = MYSQLI_NUM;
    const BOTH  = MYSQLI_BOTH;
    
    /**
     * Iterator
     *
     * @var DbResultIterator
     */
    protected $iterator;
    
    /**
     * Прединициализиация. Ля-ля.
     *
     */
    protected function onConstruct()
    {
        $this->iterator = new DbResultIterator($this->result);
    }
    
    /**
     * Получить итератор.
     *
     * @return DbResultIterator
     */
    public function getIterator()
    {
        $this->iterator->rewind();
        return $this->iterator;
    }
    
    /**
     * Возвращает массив данных.
     * 
     * @return array
     */
    public function fetch()
    {
        return $this->iterator->fetch();
    }
    
    /**
     * Возвращает массив с типом ключей
     * указанным пользователем.
     *
     * @param int $type
     * @return array
     */
    public function fetchArray($type = self::BOTH)
    {
        return $this->iterator->fetch($type);
    }
    
    /**
     * Возвращает ассоциативный массив.
     * По сути алиас метода fetch.
     *
     * @return array
     */
    public function fetchAssoc()
    {
        return $this->iterator->fetch(self::ASSOC);
    }
    
    /**
     * Возвращает числовой массив.
     *
     * @return array
     */
    public function fetchRow()
    {
        return $this->iterator->fetch(self::NUM);
    }
    
    /**
     * Получить значение колонки.
     *
     * @param string $field     имя колонки
     * @param int $seek         номер строки
     * @return array
     */
    public function fetchField($field, $seek = false)
    {
        /* прокрутка к нужной позиции при необходимости */
        if ($seek !== false) {
            $this->iterator->seek($seek);
        }
        
        $data   = $this->iterator->fetch();
        return (isset($data[$field])) ? $data[$field] : false;
    }
    
    /**
     * Получить все значения.
     *
     * @param string $key       если необходимо использовать значение как ключ
     * @return array
     */
    public function fetchAll($key = null)
    {
        return $this->getIterator()->export($key);
    }
    
    /**
     * Возвращает запись завернутую в объект
     * унаследованный от DbRecord.
     * 
     * @param $class
     * @return DbRecord
     */
    public function fetchAsObject($class)
    {
        if ($row = $this->fetch()) {
            return new $class($row);
        } else {
            return false;
        }
    }
    
    /**
     * Возвращает список завернутых в объект. 
     * Объект должен наследоваться от DbRecord.
     * 
     * @param $class extends DbRecord
     * @param $key
     * @return array
     */
    public function fetchAsObjectAll($class, $key = null)
    {
        $objects = array();
        if(isset($key) && $this->count()) {
            while($row = $this->fetchAsObject($class)) {
                $objects[$row[$key]] = $row;
            }
        } else {
            while($row = $this->fetchAsObject($class)) {
                $objects[] = $row;
            }
        }
        
        return $objects;
    }
    
    /**
     * Возвращает количество записей.
     *
     * @return int
     */
    public function count()
    {
        return $this->iterator->count();
    }
    
    /**
     * Освобождаем ресурс результата выборки.
     * 
     * @return boolean
     */
    public function free()
    {
        if($this->iterator instanceof DbResultIterator)
        {
            return $this->iterator->free();
        }
        
        return true;
    }
    
    /**
     * Сбросить указатель.
     *
     * @return DbResultSelect
     */
    public function rewind()
    {
        return $this->getIterator()->rewind();
    }
    
    /**
     * Выполняем сохранение данных при сериализации.
     *
     * @return array
     */
    public function __sleep()
    {
        $this->iterator  = new CacheIterator($this->iterator->export());
        return array('iterator');
    }
    
    /**
     * Просыпаемся после восстановления объекта из кеша.
     *
     * @return boolean
     */
    public function __wakeup()
    {
        return true;
    }
}

?>